package com.syni.mdd.sjb.common.gateway.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @className RedisTemplateUtils
 * @description TOO
 * @Author cfx
 * @DATE 2019/5/5 18:19
 * @VERSION 1.0
 **/
@Component
public class RedisTemplateUtils {
    public static RedisTemplate redisTemplate;

    //重复尝试机制
    public static int GEN_TRY_NUM = 10000;

    public static final int MAX_GET_RUN = 10000;

    //分布式锁
    public static final int DISTRIBTUED_LOCK_EXPIRE = 60 * 2;


    public static void delete(String key) {
        if(redisTemplate.hasKey(key)){
            redisTemplate.delete(key);
        }
    }

    public static boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    public static boolean noHasKey(String key,Integer waitSecond){
        int statCount = 0;
        boolean noHasKey = true;
        while (true) {
            if (statCount == waitSecond) {
                noHasKey = false;
                break;
            }
            if (!redisTemplate.hasKey(key)) {
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            statCount++;
        }
        return noHasKey;
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        RedisTemplateUtils.redisTemplate = redisTemplate;
    }

    public static RedisTemplate getRedisTemplate(){
        return redisTemplate;
    }

    /** 
     * @Description: 分布式锁（加锁）
     * @Author: cfx 
     * @Date: 2019/10/17 
     */
    public static Boolean addLock(String redisKey){
        return addLockHanle(redisKey, MAX_GET_RUN);
    }

    /**
     * @Description: 分布式锁（加锁）
     * @Author: cfx
     * @Date: 2019/10/17
     * @Param redisKey 要锁住的键
     * @Param tryNum 尝试重复获取次数
     */
    private static Boolean addLockHanle(String redisKey,Integer tryNum){
        int count = 0;
        while (count < tryNum){
            if(redisTemplate.opsForValue().setIfAbsent(redisKey,1, DISTRIBTUED_LOCK_EXPIRE,TimeUnit.SECONDS)){
                return true;
            }
            count++;
        }
        return false;
    }

    /**
     * @Description: 分布式锁（加锁）
     * @Author: cfx
     * @Date: 2019/10/17
     */
    public static Boolean addLock(String redisKey,Integer tryNum){
        return addLockHanle(redisKey,tryNum);
    }

    /**
     * @Description: 分布式锁（加锁）
     * @Author: cfx
     * @param redisKey
     * @param waitNum 尝试重复获取次数（间隔1000毫秒）
     * @Date: 2019/10/17
     */
    public static boolean addLockCanWait(String redisKey,Integer waitNum){
        int addNum = 0;
        while (true) {
            if (redisTemplate.opsForValue().setIfAbsent(redisKey, 1, DISTRIBTUED_LOCK_EXPIRE, TimeUnit.SECONDS)) {
                return true;
            }
            if(addNum == waitNum){
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            addNum++;
        }
        return false;
    }

    /**
     * @Description: 分布式锁（加锁）
     * @Author: cfx
     * @param redisKey
     * @param val 锁住的值（主要解决自己的释放自己的锁问题）
     * @param waitNum 尝试重复获取次数（间隔1000毫秒）
     * @Date: 2019/10/17
     */
    public static boolean addLockCanWait(String redisKey,String val,Integer waitNum){
        int addNum = 0;
        while (true) {
            if (redisTemplate.opsForValue().setIfAbsent(redisKey, val, DISTRIBTUED_LOCK_EXPIRE, TimeUnit.SECONDS)) {
                return true;
            }
            if(addNum == waitNum){
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            addNum++;
        }
        return false;
    }



    /**
     * @Description: 分布式锁（解锁）
     * @Author: cfx
     * @Date: 2019/10/17
     */
    public static void releaseLock(String redisKey){
        if(redisTemplate.hasKey(redisKey)) {
            redisTemplate.delete(redisKey);
        }
    }

    /**
     * @Description: 分布式锁（解锁）
     * @Author: cfx
     * @Date: 2019/10/17
     */
    public static void releaseLock(String redisKey,String val){
        if(redisTemplate.hasKey(redisKey)) {
            String values = redisTemplate.opsForValue().get(redisKey).toString();
            if(val.equals(values)) {
                redisTemplate.delete(redisKey);
            }
        }
    }

}
